﻿/*
 DotNetNuke - http://www.dotnetnuke.com
 Copyright (c) 2002-2010 by DotNetNuke Corp.

 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
 documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
 the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
 to permit persons to whom the Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all copies or substantial portions 
 of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
 TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 DEALINGS IN THE SOFTWARE.

*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Threading;
using System.Web;
using System.Xml;

using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Users;
using DotNetNuke.Modules.UserDefinedTable.Security;
using DotNetNuke.Services.Localization;
using DotNetNuke.Services.Tokens;
using DotNetNuke.UI.Modules;


namespace DotNetNuke.Modules.UserDefinedTable
{


  public class UserDefinedTableController : BaseController
  {

    public UserDefinedTableController()
    { }




    public UserDefinedTableController(ModuleInfo moduleinfo)
    {
      this.initialise(moduleinfo);

    }




    public UserDefinedTableController(ModuleInstanceContext ModuleContext)
    {
      this.initialise(ModuleContext);
    }




    public UserDefinedTableController(int moduleid)
    {
      this.ModuleID = moduleid;
    }




    public UserDefinedTableController(int ModuleId, int TabId, UserInfo userInfo)
    {
      this.initialise(ModuleId, TabId, userInfo);
    }





    /// <summary>
    /// Persists a new column with Datatype string and Default Settings
    /// </summary>
    /// <param name="Fieldtitle"></param>
    /// <returns></returns>
    /// <remarks></remarks>
    public int AddField(string Fieldtitle)
    {
      return this.AddField(Fieldtitle, Null.NullInteger
        , string.Empty, false, DataTypeNames.UDT_DataType_String
        , string.Empty, true, true, true, false, string.Empty
        , string.Empty, false, string.Empty, string.Empty, string.Empty
      );
    }






    /// <summary>
    /// persists a new column setting in the database
    /// </summary>
    /// <param name="FieldTitle">ID of the column</param>
    /// <param name="before" ></param>
    /// <param name="HelpText" ></param>
    /// <param name="Required">is an entry in this column required, when adding a row?</param>
    /// <param name="FieldType">type name of data field</param>
    /// <param name="default">default value, entered when a new row is added</param>
    /// <param name="visible">is this column visible in list view?</param>
    /// <param name="ShowOnEdit" ></param>
    /// <param name="IsPrivateColumn"></param> 
    /// <param name="searchable">is this column available for search in list view?</param>
    /// <param name="InputSettings">additional settings stored in single string</param>
    /// <param name="OutputSettings">additional settings stored in single string</param>
    /// <param name="NormalizeFlag">display flag, usage dependant on data type</param>
    /// <param name="validationRule">optional expresion that needs to be true, to successfully enter a record</param>
    /// <param name="validationMessage">displayed, if validation rules is eveluated to "false"</param>
    /// <returns>The ID of the created Field</returns>
    public int AddField(
      string FieldTitle, int before, string HelpText
      , bool Required, string FieldType
      , string Default, bool Visible, bool ShowOnEdit
      , bool Searchable, bool IsPrivateColumn, string InputSettings
      , string OutputSettings, bool NormalizeFlag, string validationRule
      , string validationMessage, string EditStyle
    )
    {
      return DataProvider.Instance().AddField(
        this.ModuleID, FieldTitle, before
        , HelpText, Required, FieldType
        , Default, Visible, ShowOnEdit
        , Searchable, IsPrivateColumn, InputSettings
        , OutputSettings, NormalizeFlag, validationRule
        , validationMessage, EditStyle
      );
    }




    private int AddRow()
    {
      return DataProvider.Instance().AddRow(this.ModuleID);
    }




    private DataSet BuildMainDataSet(DataTable fieldsTable, IDataReader dr, bool RowMode)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.BuildMainDataSet"); 
      
      fieldsTable.Columns.Add(FieldsTableColumn.ValueColumn, typeof(string));
      fieldsTable.Columns.Add(FieldsTableColumn.SortColumn, typeof(string));

      string strFields = "";
      string xmlEncodedTitle;
      
      foreach (DataRow current in fieldsTable.Rows)
      {
        strFields += string.Format("{0}{1}|", !string.IsNullOrEmpty((string)strFields) ? "," : string.Empty, (string)current[FieldsTableColumn.Title]);

        if (RowMode)
          strFields += "String";
        
        else
          //DataSet expects the FieldType to be in the namespace "System."
          //so replace all UDT-specific field types by their .net-equivalent
          strFields += DataType.ByName((string)current[FieldsTableColumn.Type]).SystemTypeName;

        //needed for generic Xsl Transformations - Data Names is XmlEncoded too
        xmlEncodedTitle = XmlConvert.EncodeName((string)current[FieldsTableColumn.Title]);
        current[FieldsTableColumn.ValueColumn] = xmlEncodedTitle;

        //gets altered in RenderValuesToHtmlInsideDataSet depending on Datatype
        current[FieldsTableColumn.SortColumn] = xmlEncodedTitle;
      }

      //converts a data reader with serialized fields into a typed data set
      DataSet ds = DotNetNuke.Common.Globals.BuildCrossTabDataSet(
        "UserDefinedTable", dr, DataTableColumn.RowId + "|Int32"
        , strFields, DataTableColumn.RowId, FieldsTableColumn.Title
        , string.Empty, DataTableColumn.Value, string.Empty
        , CultureInfo.InvariantCulture
      );

      dr.Close();

      ds.Tables[0].TableName = DataSetTableName.Data;
      fieldsTable.TableName = DataSetTableName.Fields;
      ds.Tables.Add(fieldsTable);

      System.Web.HttpContext.Current.Trace.Write("UDTC.BuildMainDataSet done");

      return ds;
    }





    /// <summary>
    /// Returns the name of the first column with a given column type (valuable for Track Columns)
    /// </summary>
    /// <param name="ds">DataSet with column definitions</param>
    /// <param name="DataType">type to be searched</param>
    /// <returns>name of the column</returns>
    public string ColumnNameByDataType(DataSet ds, string DataType)
    {
      foreach (DataRow current in ds.Tables[DataSetTableName.Fields].Rows)
        if ((string)current[FieldsTableColumn.Type] == DataType)
          return (string)current[FieldsTableColumn.Title];
        
      return string.Empty;
    }




    public DataTable Context()
    {
      return this.Context("", "", "", "");
    }





    public DataTable Context(string SearchInput, string orderBy, string orderDirection, string paging)
    {
      return this.Context(this.Configuration, this.User, SearchInput, orderBy, orderDirection, paging);
    }




    public DataTable Context(ModuleInfo moduleInfo, UserInfo userInfo, string SearchInput, string orderBy, string orderDirection, string paging)
    {
      DateTime now;

      HttpRequest request = System.Web.HttpContext.Current.Request;
      orderBy = Utilities.CStrN(orderBy, "UserDefinedRowId");
      orderDirection = Utilities.CStrN(orderDirection, "ascending");
      DataTable table2 = new DataTable("Context");
      table2.Columns.Add("ModuleId", typeof(int));
      table2.Columns.Add("TabId", typeof(int));
      table2.Columns.Add("PortalId", typeof(int));
      table2.Columns.Add("UserName", typeof(string));
      table2.Columns.Add("BestUserName", typeof(string));
      table2.Columns.Add("DisplayName", typeof(string));
      table2.Columns.Add("ApplicationPath", typeof(string));
      table2.Columns.Add("HomePath", typeof(string));
      table2.Columns.Add("UserRoles", typeof(string));
      table2.Columns.Add("IsAdministratorRole", typeof(bool));
      table2.Columns.Add("Parameter", typeof(string));
      table2.Columns.Add("OrderBy", typeof(string));
      table2.Columns.Add("OrderDirection", typeof(string));
      table2.Columns.Add("CurrentCulture", typeof(string));
      table2.Columns.Add("LocalizedString_Search", typeof(string));
      table2.Columns.Add("LocalizedString_Page", typeof(string));
      table2.Columns.Add("LocalizedString_Of", typeof(string));
      table2.Columns.Add("LocalizedString_First", typeof(string));
      table2.Columns.Add("LocalizedString_Previous", typeof(string));
      table2.Columns.Add("LocalizedString_Next", typeof(string));
      table2.Columns.Add("LocalizedString_Last", typeof(string));
      table2.Columns.Add("NowInTicks", typeof(long));
      table2.Columns.Add("TodayInTicks", typeof(long));
      table2.Columns.Add("TicksPerDay", typeof(long));
      table2.Columns.Add("LocalizedDate", typeof(string));
      table2.Columns.Add("Now", typeof(DateTime));

      if ( !string.IsNullOrEmpty(paging) )
        table2.Columns.Add("Paging", typeof(int));

      DataRow row = table2.NewRow();
      row["ModuleId"] = moduleInfo.ModuleID;
      row["TabId"] = moduleInfo.TabID;
      row["PortalId"] = moduleInfo.PortalID;
      if (userInfo.Username == null)
      {
        row["DisplayName"] = Definition.NameOfAnonymousUser;
        row["UserName"] = Definition.NameOfAnonymousUser;
      }
      else
      {
        row["DisplayName"] = userInfo.DisplayName;
        row["UserName"] = userInfo.Username;
      }
      row["BestUserName"] = row["DisplayName"];
      row["HomePath"] = DotNetNuke.Common.Globals.GetPortalSettings().HomeDirectory;
      row["ApplicationPath"] = request.ApplicationPath == "/" ? "" : request.ApplicationPath;
      row["UserRoles"] = ModuleSecurity.RoleNames(userInfo);

      if (ModuleSecurity.IsAdministrator())
        row["IsAdministratorRole"] = true;

      row["Parameter"] = SearchInput;
      row["OrderBy"] = orderBy;
      row["OrderDirection"] = orderDirection == "DESC" ? "descending" : "ascending";
      row["CurrentCulture"] = new DotNetNuke.Services.Localization.Localization().CurrentCulture;

      if ( !string.IsNullOrEmpty(paging) )
        row["Paging"] = int.Parse(paging);

      row["LocalizedString_Search"] = DotNetNuke.Services.Localization.Localization.GetString("Search.Text", Definition.SharedRessources);
      row["LocalizedString_Page"] = DotNetNuke.Services.Localization.Localization.GetString("PagingPage.Text", Definition.SharedRessources);
      row["LocalizedString_of"] = DotNetNuke.Services.Localization.Localization.GetString("PagingOf.Text", Definition.SharedRessources);
      row["LocalizedString_First"] = DotNetNuke.Services.Localization.Localization.GetString("PagingFirst.Text", Definition.SharedRessources);
      row["LocalizedString_Previous"] = DotNetNuke.Services.Localization.Localization.GetString("PagingPrevious.Text", Definition.SharedRessources);
      row["LocalizedString_Next"] = DotNetNuke.Services.Localization.Localization.GetString("PagingNext.Text", Definition.SharedRessources);
      row["LocalizedString_Last"] = DotNetNuke.Services.Localization.Localization.GetString("PagingLast.Text", Definition.SharedRessources);
      UserTime time2 = new UserTime();

      if (userInfo.Username == null)
        now = DateTime.Now;

      else
        now = time2.ConvertToUserTime(DateTime.Now, (double)userInfo.Profile.TimeZone);

      row["Now"] = now;
      row["LocalizedDate"] = now.ToString("g", Thread.CurrentThread.CurrentCulture);
      row["NowInTicks"] = now.Ticks;
      row["TodayInTicks"] = DateTime.Today.Ticks;
      row["TicksPerDay"] = 0xc92a69c000L;

      table2.Rows.Add(row);

      System.Web.HttpContext.Current.Trace.Write("build UDTC.Context ok");

      return table2;
    }





    /// <summary>
    /// persists deletion of a field into the database
    /// </summary>
    /// <param name="UserDefinedFieldId">ID of the column</param>
    public void DeleteField(int UserDefinedFieldID)
    {
      DataProvider.Instance().DeleteField(UserDefinedFieldID);
    }





    /// <summary>
    /// deletes a data row in the database
    /// </summary>
    /// <param name="UserDefinedRowId">ID of the row to be deleted</param>
    public void DeleteRow(int UserDefinedRowId)
    {
      TrackingController.OnAction(TrackingController.Trigger.Delete, UserDefinedRowId, this);
      DataProvider.Instance().DeleteRow(UserDefinedRowId, this.ModuleID);
    }






    /// <summary>
    /// deletes all data rows of a module in the database
    /// </summary>
    public void DeleteRows()
    {
      DataProvider.Instance().DeleteRows(this.ModuleID);
    }





    public bool FieldHasData(int FieldID)
    {
      return (DataProvider.Instance().GetFieldDataCount(FieldID) > 0);
    }





    /// <summary>
    /// fills all missing values for a field in all rows with default values.
    /// If not default is provided or all fields are already initialized, nothing is
    /// changed.
    /// </summary>
    /// <param name="FieldID">ID of the Field. 
    ///                       If this param is omitted, all fields will be applied.</param>
    /// <param name="DefaultExpression">Expression to be filled in, either constant or 
    ///                       containing tokens.</param>
    public void FillDefaultData(int FieldID, string DefaultExpression)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.FillDefaultData");

      DotNetNuke.Services.Tokens.TokenReplace replace = new DotNetNuke.Services.Tokens.TokenReplace()
      {
        ModuleId = this.ModuleID,
        ModuleInfo = this.Configuration
      };

      if (replace.ContainsTokens(DefaultExpression))
      {
        DataSet dataSet = this.GetDataSet(false);
        string CreatedByColumnName = this.ColumnNameByDataType(dataSet, DataTypeNames.UDT_DataType_CreatedBy);
        string fieldValue;
        string user;

        foreach (DataRow current in dataSet.Tables[DataSetTableName.Data].Rows)
        {
          user = "";
          user = current[CreatedByColumnName].ToString();

          if (user == Definition.NameOfAnonymousUser)
            user = string.Empty;

          replace.User = UserController.GetUserByName(this.PortalId, user);
          fieldValue = replace.ReplaceEnvironmentTokens(DefaultExpression, current);
          DataProvider.Instance().UpdateData((int)current["UserDefinedRowID"], FieldID, fieldValue);
        }

      }
      else
        DataProvider.Instance().FillDefaultData(this.ModuleID, FieldID, DefaultExpression);

      DataProvider.Instance().FillDefaultData(this.ModuleID, FieldID, DefaultExpression);

      System.Web.HttpContext.Current.Trace.Write("UDTC.FillDefaultData done");
    }





    /// <summary>
    /// Gets all Data values of an UDT table (module) from the Database as DataSet
    /// </summary>
    /// <returns>All field values as DataSet (prerendered)</returns>
    public DataSet GetDataSet()
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.GetDataSet()");
      return this.GetDataSet(true);
      
    }





    /// <summary>
    /// Gets all Data values of an UDT table (module) from the Database as DataSet
    /// </summary>
    /// <param name="WithPreRenderedValues">specifies, whether links, dates etc. shall be prerendered for XML output</param>
    /// <returns>All field values as DataSet</returns>
    public DataSet GetDataSet(bool WithPreRenderedValues)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.GetDataSet(bool WithPreRenderedValues)"); 
      
      DataSet ds;
      
      DataTable fieldsTable = this.GetFieldsTable(false, false);

      //read rows with data for current module from db
      using (IDataReader reader = DataProvider.Instance().GetRows(this.ModuleID))
      {
        ds = this.BuildMainDataSet(fieldsTable, reader, false);
      }

      this.SetEditLinksAndVisibilityBasedOnPermissions(ds);

      if (WithPreRenderedValues)
      {
        System.Web.HttpContext.Current.Trace.Write("UDTC.GetDataSet, WithPreRenderedValues = true");
        this.RenderValuesToHtmlInsideDataSet(ds);
      }

      System.Web.HttpContext.Current.Trace.Write("UDTC.GetDataSet(bool WithPreRenderedValues) done");

      ds.Namespace = "DotNetNuke/UserDefinedTable";
      return ds;
    }





    /// <summary>
    /// Gets all Data values of an UDT table (module) from the Database as DataSet
    /// </summary>
    /// <returns>All field values as DataSet (prerendered)</returns>
    public DataSet GetDataSet(int ModuleID)
    {
      this.initialise(ModuleID);
      return this.GetDataSet(true);
    }





    /// <summary>
    /// Gets all field definitions for one UDT table (module) from the database
    /// </summary>
    /// <returns>All field settings as DataTable</returns>
    public DataTable GetFieldsTable()
    {
      return this.GetFieldsTable(false);
    }





    /// <summary>
    /// Gets all field definitions for one UDT table (module) from the database
    /// </summary>
    /// <param name="AddNewColumn">specifies, whether a new column shall be added</param>
    /// <returns>All field settings as DataTable</returns>
    public DataTable GetFieldsTable(bool AddNewColumn)
    {
      return this.GetFieldsTable(AddNewColumn, true);
    }






    /// <summary>
    /// Gets all field definitions for one UDT table (module) from the database
    /// </summary>
    /// <param name="AddNewColumn">specifies, whether a new column shall be added</param>
    /// <param name="AddAuditColumns">specifies, whether colums for creation and update (user and timestamp) shall be added</param>
    /// <returns>All field settings as DataTable</returns>
    public DataTable GetFieldsTable(bool AddNewColumn, bool AddSystemColumns)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.GetFieldsTable");

      DataTable table;
      using (IDataReader reader = DataProvider.Instance().GetFields(this.ModuleID))
      {
        table = DotNetNuke.Common.Globals.ConvertDataReaderToDataTable(reader);
      }
      System.Web.HttpContext.Current.Trace.Write("UDTC.GetFieldsTable, ConvertDataReaderToDataTable ok");

      //when table has no fields, add system fields..
      if (AddSystemColumns && (table.Rows.Count == 0))
      {
        int num = 0;

        foreach (string str in DataType.SystemDataTypes().Keys)
          this.AddField(str, num, string.Empty
            , true, DataType.SystemDataTypes()[str]
            , string.Empty, false, false
            , false, false, string.Empty
            , string.Empty, false, string.Empty
            , string.Empty, string.Empty
          );
        
        return this.GetFieldsTable(AddNewColumn);
      }

      if (AddNewColumn)
      {
        int count = table.Rows.Count;
        int num2 = 0;

        while (count >= 1)
        {
          if (DataType.ByName(table.Rows[count - 1]["FieldType"].ToString()).IsUserDefinedField)
            break;
          
          count--;
          num2 = int.Parse(table.Rows[count]["FieldOrder"].ToString());
        }

        DataRow row = table.NewRow();
        row[FieldsTableColumn.Id] = Null.NullInteger.ToString();
        row[FieldsTableColumn.Title] = string.Empty;
        row[FieldsTableColumn.Required] = false;
        row[FieldsTableColumn.Type] = "String";
        row[FieldsTableColumn.Default] = string.Empty;
        row[FieldsTableColumn.Visible] = true;
        row[FieldsTableColumn.Searchable] = false;
        row[FieldsTableColumn.IsPrivate] = false;
        row[FieldsTableColumn.NormalizeFlag] = false;
        row[FieldsTableColumn.Order] = num2;
        row[FieldsTableColumn.ShowOnEdit] = true;

        table.Rows.InsertAt(row, count);
      }

      System.Web.HttpContext.Current.Trace.Write("UDTC.GetFieldsTable done");

      return table;
    }





    /// <summary>
    /// get value for maximal field size
    /// </summary>
    /// <returns>the maximal Fieldsize (number of characters), that can be stored in data field</returns>
    public static int GetMaxFieldSize()
    {
      return DataProvider.Instance().GetMaxFieldSize();
    }





    public DataSet GetRow(int UserDefinedRowId)
    {
      return this.GetRow(UserDefinedRowId, false);
    }





    public DataSet GetRow(int UserDefinedRowId, bool WithPreRenderedValues)
    {
      DataSet set;
      DataTable fieldsTable = this.GetFieldsTable(false, false);
      using (IDataReader reader = DataProvider.Instance().GetRow(UserDefinedRowId, this.ModuleID))
      {
        set = this.BuildMainDataSet(fieldsTable, reader, true);
        if (WithPreRenderedValues)
          this.RenderValuesToHtmlInsideDataSet(set);
        
        set.Namespace = "DotNetNuke/UserDefinedTable";
      }
      return set;
    }





    public DataSet GetSchemaDataset()
    {
      DataSet row = this.GetRow(-1);
      this.RenderValuesToHtmlInsideDataSet(row);
      row.Namespace = "DotNetNuke/UserDefinedTable";
      return row;
    }





    private void RenderValuesToHtmlInsideDataSet(DataSet ds)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.RenderValuesToHtmlInsideDataSet(DataSet ds)");

      foreach (string current in DataType.AllDataTypes)
      {
        System.Web.HttpContext.Current.Trace.Write("try render " + current);
        DataType.ByName(current).RenderValuesToHtmlInsideDataSet(ds, this.ModuleID, false);
        System.Web.HttpContext.Current.Trace.Write("render " + current + " ok ");
      }

      System.Web.HttpContext.Current.Trace.Write("UDTC.RenderValuesToHtmlInsideDataSet(DataSet ds) ok");
    }





    /// <summary>
    /// delete a whole table of a module. 
    /// </summary>
    public void ResetModule()
    {
      DataProvider.Instance().Reset(this.ModuleID);
    }






    private void SetEditLinksAndVisibilityBasedOnPermissions(DataSet ds)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.SetEditLinksAndVisibilityBasedOnPermissions " + ((this.User != null) && (this.TabId != Null.NullInteger)).ToString() );

      if ((this.User != null) && (this.TabId != Null.NullInteger))
      {
        //Provide a permission aware EditLink as an additional column to the dataset
        ModuleSecurity security = new ModuleSecurity(this.ModuleID, this.TabId, this.Settings);
        string CreatedByColumnName = this.ColumnNameByDataType(ds, DataTypeNames.UDT_DataType_CreatedBy);
        ds.Tables[DataSetTableName.Data].Columns.Add(DataTableColumn.EditLink, typeof(string));
        string NavigateUrlTemplate = DotNetNuke.Common.Globals.NavigateURL(this.TabId, "edit", new string[] { "mid=" + this.ModuleID.ToString(), DataTableColumn.RowId + "={0}" });

        string rowCreatorUserName;

        foreach(DataRow current in ds.Tables[DataSetTableName.Data].Rows)
        {
          rowCreatorUserName = (string)current[CreatedByColumnName];
          bool isUsersOwnRow = (rowCreatorUserName == this.User.Username) && (rowCreatorUserName != Definition.NameOfAnonymousUser);

          if (security.IsAllowedToEditRow(isUsersOwnRow))
            current[DataTableColumn.EditLink] = string.Format(NavigateUrlTemplate, current[DataTableColumn.RowId]);
          
        }

        foreach (DataRow row2 in ds.Tables[DataSetTableName.Fields].Rows)
          row2[FieldsTableColumn.Visible] = Convert.ToBoolean(row2[FieldsTableColumn.Visible]) || (security.IsAllowedToSeeAllUserDefinedColumns() && (DataType.ByName((string)row2[FieldsTableColumn.Type]).IsUserDefinedField || Utilities.CBoolN(this.Settings[SettingName.ShowSystemColumns], false)));
        
      }

      System.Web.HttpContext.Current.Trace.Write("UDTC.SetEditLinksAndVisibilityBasedOnPermissions done");
    }




    /// <summary>
    /// swap the ordinal position of two columns in a table definition.
    /// </summary>
    /// <param name="FirstUserDefinedFieldID">ID of the first column</param>
    /// <param name="SecondUserDefinedFieldID">ID of the second column</param>
    public void SwapFieldOrder(int FirstUserDefinedFieldID, int SecondUserDefinedFieldID)
    {
      if (FirstUserDefinedFieldID != SecondUserDefinedFieldID)
        DataProvider.Instance().SwapFieldOrder(FirstUserDefinedFieldID, SecondUserDefinedFieldID);
      
    }




    /// <summary>
    /// updates an existing data value in the database. 
    /// </summary>
    /// <param name="UserDefinedRowId">ID of the row to be deleted</param>
    /// <param name="UserDefinedFieldID">ID of the column (unique for all modules)</param>
    /// <param name="FieldValue">New Value or empty string, to delete value</param>
    private void UpdateData(int UserDefinedRowId, int UserDefinedFieldID, string FieldValue)
    {
      DataProvider.Instance().UpdateData(UserDefinedRowId, UserDefinedFieldID, FieldValue);
    }





    /// <summary>
    /// persists an altered column setting in the database
    /// </summary>
    /// <param name="UserDefinedFieldID">ID of the column field</param>
    /// <param name="FieldTitle">ID of the column</param>
    /// <param name="Required">is an entry in this column required, when adding a row?</param>
    /// <param name="FieldType">type name of data field</param>
    /// <param name="default">default value, entered when a new row is added</param>
    /// <param name="visible">is this column visible in list view?</param>
    /// <param name="searchable">is this column available for search in list view?</param>
    /// <param name="InputSettings">additional settings stored in single string</param>
    /// <param name="OutputSettings">additional settings stored in single string</param>
    /// <param name="NormalizeFlag">display flag, usage dependant on data type</param>
    /// <param name="validationRule">optional expresion that needs to be true, to successfully enter a record</param>
    /// <param name="validationMessage">displayed, if validation rules is eveluated to "false"</param>
    public void UpdateField(int UserDefinedFieldID, string FieldTitle, string HelpText
      , bool Required, string FieldType, string Default
      , bool Visible, bool ShowOnEdit, bool Searchable
      , bool IsPrivateColumn, string InputSettings, string OutputSettings
      , bool NormalizeFlag, string validationRule, string validationMessage
      , string EditStyle
    )
    {
      DataProvider.Instance().UpdateField(
        UserDefinedFieldID, FieldTitle, HelpText
        , Required, FieldType, Default
        , Visible, ShowOnEdit, Searchable
        , IsPrivateColumn, InputSettings, OutputSettings
        , NormalizeFlag, validationRule, validationMessage
        , EditStyle
      );
    }





    public void UpdateRow(DataSet ds)
    {
      this.UpdateRow(ds, 0, false);
    }





    public void UpdateRow(DataSet ds, int RowNr, bool IsDataToImport)
    {
      System.Web.HttpContext.Current.Trace.Write("enter UDTC.UpdateRow"); 

      int num;

      DataRow row = ds.Tables[DataSetTableName.Data].Rows[RowNr];
      bool rowHasContent = false;

      string strColumnName;
      string strValueColumn;

      foreach (DataRow field in ds.Tables[DataSetTableName.Fields].Rows)
      {
        if (DataType.ByName((string)field[FieldsTableColumn.Type]).IsUserDefinedField)
        {
          strColumnName = (string)field[FieldsTableColumn.Title];
          strValueColumn = IsDataToImport && ds.Tables[DataSetTableName.Data].Columns.Contains(strColumnName + DataTableColumn.Appendix_Original) ? strColumnName + DataTableColumn.Appendix_Original : strColumnName;
          rowHasContent = !string.IsNullOrEmpty(Utilities.CStrN(row[strValueColumn], "") );

          if (rowHasContent)
            break;

        }
      }

      num = (int)row[DataTableColumn.RowId];
      bool flag = IsDataToImport || (num == -1);

      if (flag && rowHasContent)
      {
        num = this.AddRow();
        row[DataTableColumn.RowId] = num;
      }

      if (rowHasContent)
      {

        foreach (DataRow field in ds.Tables[DataSetTableName.Fields].Rows)
        {
          strColumnName = (string)field[FieldsTableColumn.Title];
          strValueColumn = !IsDataToImport && ds.Tables[DataSetTableName.Data].Columns.Contains(strColumnName + DataTableColumn.Appendix_Original) ? strColumnName + DataTableColumn.Appendix_Original : strColumnName;

          if (ds.Tables[DataSetTableName.Data].Columns.Contains(strValueColumn))
            this.UpdateData(num, (int)field[FieldsTableColumn.Id], Utilities.CStrN(row[strValueColumn], ""));
        }

        if (!IsDataToImport)
        {
          if (flag)
            TrackingController.OnAction(TrackingController.Trigger.New, ds, this);

          else
            TrackingController.OnAction(TrackingController.Trigger.Update, ds, this);

        }
      }
      else
        this.DeleteRow(num);

      System.Web.HttpContext.Current.Trace.Write("UDTC.UpdateRow done"); 

    }


  }

}

